package com.baidu.elinkagescroll.view;

import com.ryan.ohos.extension.event.DispatchHelper;
import com.ryan.ohos.extension.event.impl.ViewGroupHelper;
import com.ryan.ohos.extension.event.impl.ViewHelper;
import com.ryan.ohos.extension.event.interfaces.View;
import com.ryan.ohos.extension.event.interfaces.ViewGroup;
import com.ryan.ohos.extension.nested.*;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.StackLayout;
import ohos.app.Context;

import ohos.multimodalinput.event.TouchEvent;

/**
 * 业务方可能不会直接提供RecyclerView
 * 而是会在RecyclerView外面包一层FrameLayout做一些类似吸顶的逻辑
 *
 * @since 2021/7/15
 */
public class NestedFrameLayout extends StackLayout implements NestedScrollingParent, NestedScrollingChild, View, ViewGroup, Component.TouchEventListener {
    private NestedScrollingChildHelper mChildHelper;
    private NestedScrollingParentHelper mParentHelper;
    private ViewGroupHelper mViewGroupHelper;
    private ViewHelper mViewHelper;

    /**
     * init NestedFrameLayout
     *
     * @param context context
     */
    public NestedFrameLayout(Context context) {
        this(context, null);
    }

    /**
     *  init NestedFrameLayout
     *
     * @param context context
     * @param attrSet attrSet
     */
    public NestedFrameLayout(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * init NestedFrameLayout
     *
     * @param context context
     * @param attrSet attrSet
     * @param styleName styleName
     */
    public NestedFrameLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        mChildHelper = new NestedScrollingChildHelper(this);
        mParentHelper = new NestedScrollingParentHelper(this);

        mViewGroupHelper = new ViewGroupHelper(this);
        mViewHelper = new ViewHelper(this);
        setTouchEventListener(this);
        setNestedScrollingEnabled(true);
    }

    @Override
    public boolean dispatchTouchEvent(TouchEvent ev) {
        if (ev.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
            startNestedScroll(NestedScrollingHelper.SCROLL_AXIS_VERTICAL, NestedScrollingHelper.TYPE_TOUCH);
        }
        return mViewGroupHelper.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(TouchEvent touchEvent) {
        return false;
    }

    @Override
    public boolean isConsumed() {
        return mViewHelper.isConsumed();
    }

    // NestedScrollingChild BEGIN
    @Override
    public void setNestedScrollingEnabled(boolean enabled) {
        mChildHelper.setNestedScrollingEnabled(enabled);
    }

    @Override
    public boolean isNestedScrollingEnabled() {
        return mChildHelper.isNestedScrollingEnabled();
    }

    @Override
    public boolean startNestedScroll(int axes, int type) {
        return mChildHelper.startNestedScroll(axes, type);
    }

    @Override
    public void stopNestedScroll(int type) {
        mChildHelper.stopNestedScroll(type);
    }

    @Override
    public boolean hasNestedScrollingParent(int type) {
        return mChildHelper.hasNestedScrollingParent(type);
    }

    @Override
    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow, int type, int[] consumed) {
        return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow, type, consumed);
    }

    @Override
    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow, int type) {
        return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type);
    }

    @Override
    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
        return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
    }

    @Override
    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
        return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
    }

    // NestedScrollingParent BEGIN
    @Override
    public boolean onStartNestedScroll(Component child, Component target, int axes, int type) {
        return axes != 0;
    }

    @Override
    public void onNestedScrollAccepted(Component child, Component target, int axes, int type) {
        mParentHelper.onNestedScrollAccepted(child, target, axes, type);
    }

    @Override
    public boolean onNestedFling(Component target, float velocityX, float velocityY, boolean consumed) {
        return dispatchNestedFling(velocityX, velocityY, consumed);
    }

    @Override
    public boolean onNestedPreFling(Component target, float velocityX, float velocityY) {
        return dispatchNestedPreFling(velocityX, velocityY);
    }

    @Override
    public void onNestedPreScroll(Component target, int dx, int dy, int[] consumed, int type) {
        dispatchNestedPreScroll(dx, dy, consumed, null, type);
    }

    @Override
    public void onNestedScroll(Component target,
                                int dxConsumed, int dyConsumed,
                                int dxUnconsumed, int dyUnconsumed, int type, int[] consumed) {
        dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null, type, consumed);
    }

    @Override
    public void onStopNestedScroll(Component child, int type) {
        mParentHelper.onStopNestedScroll(child, type);
    }

    @Override
    public int getNestedScrollAxes() {
        return mParentHelper.getNestedScrollAxes();
    }

    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        mViewGroupHelper.requestDisallowInterceptTouchEvent(disallowIntercept);
    }

    @Override
    public boolean onInterceptTouchEvent(TouchEvent touchEvent) {
        return false;
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        return DispatchHelper.dispatch(component, touchEvent);
    }
}
